package com.gitee.qdbp.general.trade.biz.order.main.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.tools.utils.VerifyTools;

public abstract class AmountTools {

    private static Logger log = LoggerFactory.getLogger(AmountTools.class);

    /**
     * 计算单价总价折扣: 只有单价就计算总价, 只有总价就计算单价, 有单价和总价就计算折扣, 都有就检查是否正确
     * 
     * @param bean 计算对象
     * @throws ServiceException 缺少参数或参数的金额不等于单价*数量-折扣+运费
     */
    public static void calculate(AmountBean bean) throws ServiceException {
        if (VerifyTools.isBlank(bean.getQuantity())) {
            bean.setQuantity(1);
        }
        if (VerifyTools.isBlank(bean.getFreight())) {
            bean.setFreight(0D);
        }

        if (VerifyTools.isNotBlank(bean.getPrice())) { // 单价不为空
            if (VerifyTools.isBlank(bean.getAmount())) { // 金额为空
                if (VerifyTools.isBlank(bean.getDiscount())) {
                    bean.setDiscount(0D);
                }
                // 计算金额: 金额=单价*数量-折扣+运费
                double amount = bean.getPrice() * bean.getQuantity() - bean.getDiscount() + bean.getFreight();
                bean.setAmount(amount);
            } else { // 金额不为空
                if (VerifyTools.isBlank(bean.getDiscount())) { // 折扣为空
                    // 计算折扣: 折扣=金额-单价*数量-运费
                    double discountAmount = bean.getAmount() - bean.getPrice() * bean.getQuantity() - bean.getFreight();
                    bean.setDiscount(discountAmount);
                } else { // 折扣不为空
                    // 计算金额: 金额=单价*数量-折扣+运费
                    double expectAmount = bean.getPrice() * bean.getQuantity() - bean.getDiscount() + bean.getFreight();
                    if (bean.getAmount() != expectAmount) {
                        log.error("OrderItemAmount[{}] error, expect[{}]", bean.getAmount(), expectAmount);
                        throw new ServiceException(ResultCode.PARAMETER_VALUE_ERROR);
                    }
                }
            }
        } else if (VerifyTools.isNotBlank(bean.getAmount())) { // 单价为空, 金额不为空
            if (VerifyTools.isBlank(bean.getDiscount())) {
                bean.setDiscount(0D);
            }
            // 计算单价: 单价=(金额+折扣-运费)/数量
            double goodsPrice = (bean.getAmount() + bean.getDiscount() - bean.getFreight()) / bean.getQuantity();
            bean.setPrice(Math.round(goodsPrice * 10000) / 10000D); // 保留4位小数
        } else { // 单价和金额都为空
            log.error("Params is required: GoodsPrice or GoodsAmount");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
    }

    public static class AmountBean {

        /** 单价 **/
        private Double price;
        /** 数量 **/
        private Integer quantity;
        /** 折扣金额 **/
        private Double discount;
        /** 运费 **/
        private Double freight;
        /** 总金额=单价*数量-折扣+运费 **/
        private Double amount;

        /** 单价 **/
        public Double getPrice() {
            return price;
        }

        /** 单价 **/
        public void setPrice(Double price) {
            this.price = price;
        }

        /** 数量 **/
        public Integer getQuantity() {
            return quantity;
        }

        /** 数量 **/
        public void setQuantity(Integer quantity) {
            this.quantity = quantity;
        }

        /** 折扣金额 **/
        public Double getDiscount() {
            return discount;
        }

        /** 折扣金额 **/
        public void setDiscount(Double discount) {
            this.discount = discount;
        }

        /** 运费 **/
        public Double getFreight() {
            return freight;
        }

        /** 运费 **/
        public void setFreight(Double freight) {
            this.freight = freight;
        }

        /** 总金额=单价*数量-折扣 **/
        public Double getAmount() {
            return amount;
        }

        /** 总金额=单价*数量-折扣 **/
        public void setAmount(Double amount) {
            this.amount = amount;
        }

    }
}
